Reading the card status

Latest update: June 2015

This tutorial demonstrates how to read the wireless LAN status of a FlashAir using iSDIO commands

Reading card status

The following chart shows the iSDIO register map, from the simplified specification.

The structure of the iSDIO Register Map (abstracted from SD Specifications Part E7 iSDIO Simplified Specification Version 1.10)

Commands

The iSDIO status is acquired by reading a page which starts from address 0x400 (total size: 512 bytes).

Address 0x400 to 0x4FF shows standard iSDIO status information. . Address 0x500~0x5FF shows the status of each application. By reading this section, you can get information about the FlashAir's wireless LAN.

iSDIO Status Register Map (abstracted from SD Specifications Part E7 iSDIO Simplified Specification Version)

Commands

Application Status for Wireless LAN (abstracted from SD Specifications Part E7 iSDIO Simplified Specification Version)

Commands

Making a status reading function

According to the status map above, you can make a status reading function by reading area from address 0x400.

arduino_tutorial_03.ino (Part 1)

uint8_t buffer[512];

void printByte(uint8_t value) {
  Serial.print(value >> 4, HEX);
  Serial.print(value & 0xF, HEX);
}

void printBytes(uint8_t* p, uint32_t len) {
  for (int i = 0; i < len; ++i) {
    printByte(p[i]);
  }
}

void printIPAddress(uint8_t* p) {
  Serial.print(p[0], DEC);
  Serial.print('.');
  Serial.print(p[1], DEC);
  Serial.print('.');
  Serial.print(p[2], DEC);
  Serial.print('.');
  Serial.print(p[3], DEC);
}

boolean iSDIO_status() {
  Serial.print(F("\nRead iSDIO Status Register"));
  // Read iSDIO Status Register (E7 1.10 2.2.2.1)
  memset(buffer, 0, 0x200);
  if (!card.readExtMemory(1, 1, 0x400, 0x200, buffer)) {
    return false;
  }
  // Show values in the common status area.
  Serial.print(F("\n == iSDIO Status Registers == "));
  Serial.print(F("\n [0400h] Command Write Status: "));
  if (buffer[0x000] & 0x01) Serial.print(F("CWU "));
  if (buffer[0x000] & 0x02) Serial.print(F("CWA "));
  Serial.print(F("\n [0420h] iSDIO Status: "));
  if (buffer[0x020] & 0x01) Serial.print(F("CRU "));
  if (buffer[0x020] & 0x02) Serial.print(F("ESU "));
  if (buffer[0x020] & 0x04) Serial.print(F("MCU "));
  if (buffer[0x020] & 0x08) Serial.print(F("ASU "));
  Serial.print(F("\n [0422h] iSDIO Int Enable: "));
  if (buffer[0x022] & 0x01) Serial.print(F("CRU_ENA "));
  if (buffer[0x022] & 0x02) Serial.print(F("ESU_ENA "));
  if (buffer[0x022] & 0x04) Serial.print(F("MCU_ENA "));
  if (buffer[0x022] & 0x08) Serial.print(F("ASU_ENA "));
  Serial.print(F("\n [0424h] Error Status: "));
  if (buffer[0x024] & 0x01) Serial.print(F("CRE "));
  if (buffer[0x024] & 0x02) Serial.print(F("CWE "));
  if (buffer[0x024] & 0x04) Serial.print(F("RRE "));
  if (buffer[0x024] & 0x08) Serial.print(F("APE "));
  Serial.print(F("\n [0426h] Memory Status: "));
  if (buffer[0x026] & 0x01) Serial.print(F("MEX "));
  if (buffer[0x026] & 0x02) Serial.print(F("FAT "));
  for (int i = 0; i < 8; ++i) {
    uint8_t addr = 0x40 + i * 0x14;
    Serial.print(F("\n [04"));
    printByte(addr);
    Serial.print(F("h] Command Response Status #"));
    Serial.print(i + 1, DEC);
    Serial.print(F(": "));
    if (buffer[addr] & 0x01) {
      Serial.print(F("id = "));
      Serial.print(get_u16(buffer + addr + 2), DEC);
      Serial.print(F(", sequence id = "));
      Serial.print(get_u32(buffer + addr + 4), DEC);
      Serial.print(F(", status = "));
      switch (buffer[addr + 8]) {
        case 0x00: Serial.print(F("Initial")); break;
        case 0x01: Serial.print(F("Command Processing")); break;
        case 0x02: Serial.print(F("Command Rejected")); break;
        case 0x03: Serial.print(F("Process Succeeded")); break;
        case 0x04: Serial.print(F("Process Terminated")); break;
        default:   Serial.print(F("Process Failed ")); Serial.print(buffer[addr + 8], HEX); break;
      }
    } else {
      Serial.print(F("Not registered"));
    }
  }
  // Show values in the application status area.
  Serial.print(F("\n == Wireless LAN Status Registers =="));
  Serial.print(F("\n [0500h] DLNA Status: "));
  if (buffer[0x100] & 0x01) Serial.print(F("ULR "));
  if (buffer[0x100] & 0x02) Serial.print(F("DLU "));
  if (buffer[0x100] & 0x04) Serial.print(F("CBR "));
  if (buffer[0x100] & 0x08) Serial.print(F("CDR "));
  Serial.print(F("\n [0501h] P2P Status: "));
  if (buffer[0x101] & 0x01) Serial.print(F("ILU "));
  if (buffer[0x101] & 0x02) Serial.print(F("FLU "));
  Serial.print(F("\n [0502h] PTP Status: "));
  if (buffer[0x102] & 0x01) Serial.print(F("RPO "));
  if (buffer[0x102] & 0x02) Serial.print(F("RPD "));
  if (buffer[0x102] & 0x04) Serial.print(F("RPC "));
  if (buffer[0x102] & 0x08) Serial.print(F("CPI "));
  if (buffer[0x102] & 0x10) Serial.print(F("DPI "));
  if (buffer[0x102] & 0x20) Serial.print(F("CIL "));
  Serial.print(F("\n [0504h] Application: "));
  Serial.print(buffer[0x104]);
  Serial.print(F("\n [0506h] WLAN: "));
  if ((buffer[0x106] & 0x01) == 0x00) Serial.print(F("No Scan, "));
  if ((buffer[0x106] & 0x01) == 0x01) Serial.print(F("Scanning, "));
  if ((buffer[0x106] & 0x06) == 0x00) Serial.print(F("No WPS, "));
  if ((buffer[0x106] & 0x06) == 0x02) Serial.print(F("WPS with PIN, "));
  if ((buffer[0x106] & 0x06) == 0x04) Serial.print(F("WPS with PBC, "));
  if ((buffer[0x106] & 0x08) == 0x00) Serial.print(F("Group Client, "));
  if ((buffer[0x106] & 0x08) == 0x08) Serial.print(F("Group Owner "));
  if ((buffer[0x106] & 0x10) == 0x00) Serial.print(F("STA, "));
  if ((buffer[0x106] & 0x10) == 0x10) Serial.print(F("AP, "));
  if ((buffer[0x106] & 0x60) == 0x00) Serial.print(F("Initial, "));
  if ((buffer[0x106] & 0x60) == 0x20) Serial.print(F("Infrastructure, "));
  if ((buffer[0x106] & 0x60) == 0x40) Serial.print(F("Wi-Fi Direct, "));
  if ((buffer[0x106] & 0x80) == 0x00) Serial.print(F("No Connection, "));
  if ((buffer[0x106] & 0x80) == 0x80) Serial.print(F("Connected, "));
  Serial.print(F("\n [0508h] SSID: "));
  for (int i = 0; i < 32 && buffer[0x108 + i] != 0; ++i) { 
    Serial.print((char)buffer[0x108 + i]);
  }
  Serial.print(F("\n [0528h] Encryption Mode: "));
  switch (buffer[0x128]) {
    case 0 : Serial.print(F("Open System and no encryption")); break;
    case 1 : Serial.print(F("Open System and WEP")); break;
    case 2 : Serial.print(F("Shared Key and WEP")); break;
    case 3 : Serial.print(F("WPA-PSK and TKIP")); break;
    case 4 : Serial.print(F("WPA-PSK and AES")); break;
    case 5 : Serial.print(F("WPA2-PSK and TKIP")); break;
    case 6 : Serial.print(F("WPA2-PSK and AES")); break;
    default: Serial.print(F("Unknown"));
  }
  Serial.print(F("\n [0529h] Signal Strength: "));
  Serial.print(buffer[0x129], DEC);
  Serial.print(F("\n [052Ah] Channel: "));
  if (buffer[0x12A] == 0) Serial.print(F("No connection"));
  else Serial.print(buffer[0x12A], DEC);
  Serial.print(F("\n [0530h] MAC Address: "));
  printBytes(buffer + 0x130, 6);
  Serial.print(F("\n [0540h] ID: "));
  for (int i = 0; i < 16 && buffer[0x140 + i] != 0; ++i) { 
    Serial.print((char)buffer[0x140 + i]);
  }
  Serial.print(F("\n [0550h] IP Address: "));
  printIPAddress(buffer + 0x150);
  Serial.print(F("\n [0554h] Subnet Mask: "));
  printIPAddress(buffer + 0x154);
  Serial.print(F("\n [0558h] Default Gateway: "));
  printIPAddress(buffer + 0x158);
  Serial.print(F("\n [055Ch] Preferred DNS Server: "));
  printIPAddress(buffer + 0x15C);
  Serial.print(F("\n [0560h] Alternate DNS Server: "));
  printIPAddress(buffer + 0x160);
  Serial.print(F("\n [0564h] Proxy Server: "));
  if ((buffer[0x164] & 0x01) == 0x00) Serial.print(F("Disabled"));
  if ((buffer[0x164] & 0x01) == 0x01) Serial.print(F("Enabled"));
  Serial.print(F("\n [0570h] Date: "));
  Serial.print(buffer[0x171] + 1980, DEC); Serial.print('-');
  Serial.print(buffer[0x170] >> 4, DEC); Serial.print('-');
  Serial.print(buffer[0x170] & 0xF, DEC);
  Serial.print(F("\n [0572h] Time: "));
  Serial.print(buffer[0x173] >> 3, DEC); Serial.print(':');
  Serial.print(buffer[0x172] << 3 | buffer[0x170] >> 3, DEC); Serial.print(':');
  Serial.print((buffer[0x172] & 0x1F) * 2, DEC);
  Serial.print(F("\n [0574h] HTTP Status: "));
  Serial.print(buffer[0x174] & 0xEF, DEC);
  if ((buffer[0x174] & 0x80) == 0x00) Serial.print(F(" (No Processing)"));
  if ((buffer[0x174] & 0x80) == 0x80) Serial.print(F(" (Processing)"));
  Serial.print(F("\n [0575h] Power Save Management: "));
  if ((buffer[0x175] & 0x01) == 0x00) Serial.print(F("Power Save Mode Off"));
  if ((buffer[0x175] & 0x01) == 0x01) Serial.print(F("Power Save Mode On"));
  Serial.print(F("\n [0576h] File System Management: "));
  if ((buffer[0x176] & 0x01) == 0x00) Serial.print(F("FS Information may be modified"));
  if ((buffer[0x176] & 0x01) == 0x01) Serial.print(F("FS Information shall not be modified"));
  Serial.println();

  return true;
}

Please note that Serial.print() and Serial.println() are functions to output characters on the "serial monitor", strings are enclosed by the macro F(). Generally string parameters are placed in RAM, because (according to the language specification) they can be rewritten. This means that if many characters are displayed, we'll run out of memory.

To avoid this, we use the macro F(), which places enclosed characters in ROM and does not consume RAM.

And call with setup().

arduino_tutorial_03.ino (Part 2)

void setup() {
  // Initialize UART for message print.
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  // Initialize SD card.
  Serial.print(F("\nInitializing SD card..."));  
  if (card.init(SPI_HALF_SPEED, chipSelectPin)) {
    Serial.print(F("OK"));
  } else {
    Serial.print(F("NG"));
    abort();
  }

  if (iSDIO_status()) {
    Serial.print(F("\nOK"));
  } else {
    Serial.println(F("\nFailed to read status."));
  }
}

Execution result

Example execution result

Read iSDIO Status Register
 == iSDIO Status Registers == 
 [0400h] Command Write Status: 
 [0420h] iSDIO Status: CRU 
 [0422h] iSDIO Int Enable: 
 [0424h] Error Status: 
 [0426h] Memory Status: MEX 
 [0440] Command Response Status #1: id = 3, sequence id = 0, status = Process Succeeded
 [0454] Command Response Status #2: Not registered
 [0468] Command Response Status #3: Not registered
 [047C] Command Response Status #4: Not registered
 [0490] Command Response Status #5: Not registered
 [04A4] Command Response Status #6: Not registered
 [04B8] Command Response Status #7: Not registered
 [04CC] Command Response Status #8: Not registered
 == Wireless LAN Status Registers ==
 [0500h] DLNA Status: 
 [0501h] P2P Status: 
 [0502h] PTP Status: 
 [0504h] Application: 0
 [0506h] WLAN: No Scan, No WPS, Group Client, AP, Infrastructure, No Connection, 
 [0508h] SSID: flashair_sdio
 [0528h] Encryption Mode: WPA2-PSK and AES
 [0529h] Signal Strength: 0
 [052Ah] Channel: 11
 [0530h] MAC Address: B86B23733F4F
 [0540h] ID: 
 [0550h] IP Address: 192.168.0.1
 [0554h] Subnet Mask: 255.255.255.0
 [0558h] Default Gateway: 192.168.0.1
 [055Ch] Preferred DNS Server: 192.168.0.1
 [0560h] Alternate DNS Server: 0.0.0.0
 [0564h] Proxy Server: Disabled
 [0570h] Date: 1980-0-0
 [0572h] Time: 0:0:0
 [0574h] HTTP Status: 0 (No Processing)
 [0575h] Power Save Management: Power Save Mode Off
 [0576h] File System Management: FS Information may be modified

OK

Sample code

arduino_tutorial_03.zip (23KB)

All sample code on this page is licensed under BSD 2-Clause License.